Razred Vozel
predstavlja osnovni gradnik verižnega seznama. Pri tej nalogi
bomo dodali razredu Vozel
nekaj novih metod. Za osnovno vzemite naslednjo
implementacijo:
class Vozel:
"""
Osnovni sestavni del verižnega seznama.
"""
def __init__(self, podatek=None, naslednji=None):
self.podatek = podatek
self.naslednji = naslednji
def __str__(self):
return str(self.podatek)
Razredu Vozel
dodajte metodo vrni_seznam(self)
, ki vrne seznam vseh
podatkov v verižnem seznamu. Zgled:
>>> v1 = Vozel('nedelja')
>>> v2 = Vozel('sobota', v1)
>>> v3 = Vozel('petek', v2)
>>> v3.vrni_seznam()
['petek', 'sobota', 'nedelja']
class Vozel: """ Osnovni sestavni del verižnega seznama. """ def __init__(self, podatek=None, naslednji=None): self.podatek = podatek self.naslednji = naslednji def __str__(self): return str(self.podatek) def vrni_seznam(self): """ Vrni seznam s podatki, ki so shranjeni v vozlih. """ sez = [] p = self while p is not None: sez.append(p.podatek) p = p.naslednji return sez
Razredu Vozel
dodajte metodo dodaj_na_zacetek(self, x)
, ki doda nov
vozel na začetek verižnega seznama self
, ter vrne referenco na novi vozel.
Zgled:
>>> v = Vozel('nedelja')
>>> v = v.dodaj_na_zacetek('sobota')
>>> v = v.dodaj_na_zacetek('petek')
>>> v.vrni_seznam()
['petek', 'sobota', 'nedelja']
class Vozel(Vozel): def dodaj_na_zacetek(self, x): """ Dodaj nov vozel na začetek verižnega seznama. """ return Vozel(x, self)
Razredu Vozel
dodajte metodo dodaj_na_konec(self, x)
, ki doda nov
vozel na konec verižnega seznama self
. Zgled:
>>> v = Vozel('petek')
>>> v.dodaj_na_konec('sobota')
>>> v.dodaj_na_konec('nedelja')
>>> v.vrni_seznam()
['petek', 'sobota', 'nedelja']
class Vozel(Vozel): def dodaj_na_konec(self, x): """ Dodaj nov vozel na konec verižnega seznama. """ p = self while p.naslednji != None: p = p.naslednji p.naslednji = Vozel(x)
Razredu Vozel
dodajte metodo __len__(self)
, ki vrne število vozlov v
verižnem seznamu. Zgled:
>>> v = Vozel('sobota')
>>> v.dodaj_na_konec('nedelja')
>>> v = v.dodaj_na_zacetek('petek')
>>> len(v)
3
class Vozel(Vozel): def __len__(self): """ Vrni število vozlov v verižnem seznamu. """ if self.naslednji is None: return 1 return 1 + len(self.naslednji)
Dodali bomo še nekaj funkcij za delo z verižnimi seznami.
Sestavite funkcijo stevilska_veriga(a, b)
, ki vrne verižni seznam, ki
vsebuje števila od a
do b
. Funkcija naj vrne referenco na prvi vozel.
Predpostavite, da velja a <= b
. Zgled:
>>> v = stevilska_veriga(3, 7)
>>> v.vrni_seznam()
[3, 4, 5, 6, 7]
def stevilska_veriga(a, b): """ Vrni verižni seznam, ki vsebuje vsa števila od a do b. """ if a == b: return Vozel(a) return Vozel(a, stevilska_veriga(a + 1, b))
Sestavite funkcijo seznam_sodih(vozel)
, ki kot argument dobil referenco
na vozel in vrne seznam z vsemi sodimi elementi v tem verižnem seznamu.
Predpostavite lahko, da so vsi podatki cela števila. Zgled:
>>> v = stevilska_veriga(3, 11)
>>> seznam_sodih(v)
[4, 6, 8, 10]
def seznam_sodih(vozel): """ Vrni seznam vseh sodih elementov v verižnem seznamu. """ l = [] while vozel is not None: if vozel.podatek % 2 == 0: l.append(vozel.podatek) vozel = vozel.naslednji return l
Sestavite funkcijo iz_seznama(l)
, ki kor argument sprejme seznam l
ter
vrne verižni seznam, ki kot podatke vsebuje elemente seznama l
. Funkcija
naj vrne referenco na prvi vozel. Predpostavite lahko, da je seznam l
neprazen. Zgled:
>>> v = iz_seznama(['torek', 'sreda', 'četrtek', 'petek'])
>>> v.dodaj_na_konec('sobota')
>>> v.vrni_seznam()
['torek', 'sreda', 'četrtek', 'petek', 'sobota']
def iz_seznama(l): """ Vrni verižni seznam, ki bo imel kot podatke elemente seznama l. """ prvi = Vozel(l[0]) p = prvi for i in range(1, len(l)): p.naslednji = Vozel(l[i]) p = p.naslednji return prvi
Razredu Vozel
dodajte metodo zadnji_vozel(self)
, ki vrne referenco na
zadnji vozel v verižnem seznamu. Zgled:
>>> v = iz_seznama(['sreda', 'četrtek', 'petek', 'sobota'])
>>> z = v.zadnji_vozel()
>>> print(z)
'sobota'
class Vozel(Vozel): def zadnji_vozel(self): p = self while p.naslednji is not None: p = p.naslednji return p
Razredu Vozel
dodajte metodo vstavi_na_mesto(self, n, x)
, ki dobi število
n
in podatek x
. Metoda naj na n
-to mesto v verižni seznam vstavi nov
vozel s podatkom x
. Funkcija naj vrne referenco na prvi vozel v verižnem
seznamu. Če verižni seznam ni dovolj dolg, dodajte ustrezno število vozlov,
ki imajo kot podatek None
. Zgled:
>>> v = iz_seznama(['sreda', 'četrtek', 'sobota'])
>>> v = v.vstavi_na_mesto(2, 'petek')
>>> v.vrni_seznam()
['sreda', 'četrtek', 'petek', 'sobota']
class Vozel(Vozel): def vstavi_na_mesto(self, n, x): if n == 0: return self.dodaj_na_zacetek(x) if self.naslednji == None: if n == 1: self.naslednji = Vozel(x) return self else: self.naslednji = Vozel() self.naslednji = self.naslednji.vstavi_na_mesto(n - 1, x) return self
Razred Vozel
predstavlja osnovni gradnik verižnega seznama. Pri tej nalogi
bomo dodali razredu Vozel
nekaj novih metod. Za osnovno vzemite naslednjo
implementacijo:
class Vozel:
"""
Osnovni sestavni del verižnega seznama.
"""
def __init__(self, podatek=None, naslednji=None):
self.podatek = podatek
self.naslednji = naslednji
def __str__(self):
return str(self.podatek)
Dodajte še funkcijo iz_seznama
, ki ste jo sestavili pri prejšnji nalogi in
metodo vrni_seznam
. Če želite, lahko dodate še kakšno metodo oz. funkcijo.
Razredu Vozel
dodajte metodo podvoji_verigo(self)
, ki naj sestavi in
vrne novo kopijo verige, stare pa naj ne spreminja. Zgled:
>>> v = iz_seznama([2, 3, 4, 5])
>>> v2 = v.podvoji_verigo()
>>> v2.podatek = 11
>>> v.vrni_seznam()
[2, 3, 4, 5]
>>> v2.vrni_seznam()
[11, 3, 4, 5]
class Vozel: """ Osnovni sestavni del verižnega seznama. """ def __init__(self, podatek=None, naslednji=None): self.podatek = podatek self.naslednji = naslednji def __str__(self): return str(self.podatek) def vrni_seznam(self): """ Vrni seznam s podatki, ki so shranjeni v vozlih. """ sez = [] p = self while p is not None: sez.append(p.podatek) p = p.naslednji return sez def iz_seznama(l): """ Vrni verižni seznam, ki bo imel kot podatke elemente seznama l. """ if not l: # če je seznam prazen return None prvi = Vozel(l[0]) p = prvi for i in range(1, len(l)): p.naslednji = Vozel(l[i]) p = p.naslednji return prvi class Vozel(Vozel): def podvoji_verigo(self): if self.naslednji is None: return Vozel(self.podatek) return Vozel(self.podatek, self.naslednji.podvoji_verigo())
Sestavite funkcijo stakni_verigi(v1, v2)
, ki kot argumenta prejme referenci
na dva vozla in sestavi novo verigo, ki jo dobi tako, da stakne obe verigi.
To pomeni, da morata ostati verigi v1
in v2
nespremenjeni, funkcija pa
vrne povsem novo verigo! Na primer:
>>> v1 = iz_seznama([1, 2, 3])
>>> v2 = iz_seznama([4, 5, 6])
>>> v = stakni_verigi(v1, v2)
>>> v.vrni_seznam()
[1, 2, 3, 4, 5, 6]
>>> v1.vrni_seznam()
[1, 2, 3]
def stakni_verigi(v1, v2): '''Iz verig v1 in v2 naredi novo verigo. Prvotni ostaneta nespremenjeni! ''' v = v1.podvoji_verigo() # nova, podvojena veriga # postavimo se na konec nove p = v while p.naslednji is not None: p = p.naslednji # in tej verigi dodamo kopijo verige v2 p.naslednji = v2.podvoji_verigo() return v def stakni_verigi(v1, v2): ''' "Grša oblika" Iz verig v1 in v2 naredi novo verigo. Prvotni ostaneta nespremenjeni! ''' s1 = v1.vrni_seznam() s2 = v2.vrni_seznam() return iz_seznama(s1 + s2)
Sestavite funkcijo multipliciraj_verigo(v, n)
, ki kot argumenta prejme
referenco na vozel in naravno število n
ter vrne verigo spremeni, tako da
iz vsakega vozla naredi n
zaporednih kopij. Funkcija naj vrne referenco
na prvi vozel. Na primer:
>>> v = iz_seznama([7, 5, 2])
>>> v = multipliciraj_verigo(v, 3)
>>> v.vrni_seznam()
[7, 7, 7, 5, 5, 5, 2, 2, 2]
def multipliciraj_verigo(v, n, k=None): if v is None: return None if k is None: k = n if k == 1: v.naslednji = multipliciraj_verigo(v.naslednji, n) return v v2 = Vozel(v.podatek, multipliciraj_verigo(v, n, k-1)) return v2
Sestavite funkcijo na_zadrgo(v1, v2)
, ki kot argumenta prejme referenci
na dva vozla. Funkcija naj vrne verigo, ki jo dobi tako, da "na zadrgo"
združi obe verigi. Funkcija naj vrne referenco na prvi vozel tako dobljene
verige. Na primer:
>>> v1 = iz_seznama([7, 5, 2])
>>> v2 = iz_seznama([1, 3, 4, 9, 8])
>>> v = na_zadrgo(v1, v2)
>>> v.vrni_seznam()
[7, 1, 5, 3, 2, 4, 9, 8]
def na_zadrgo(v1, v2): if v1 is None: return v2 if v2 is None: return v1 v = na_zadrgo(v1.naslednji, v2.naslednji) v1.naslednji = v2 v2.naslednji = v return v1
Sestavite funkcijo odpni_zadrgo(v)
, ki kot argument prejme referenco na
vozel ter vrne dve verigi, ki jih dobi tako, da "odpne zadrgo", tj. vozle
naj razdeli med dve verigi. Funkcija naj vrne par in sicer referenci na
začetna vozla v obeh verigah. Na primer:
>>> v = iz_seznama([7, 5, 2, 1, 3, 4, 9, 8])
>>> v1, v2 = odpni_zadrgo(v)
>>> v1.vrni_seznam()
[7, 2, 3, 9]
>>> v2.vrni_seznam()
[5, 1, 4, 8]
def odpni_zadrgo(v): if v is None: return None, None vn = v.naslednji if vn is None: return v, None v1, v2 = odpni_zadrgo(v.naslednji.naslednji) v.naslednji = v1 vn.naslednji = v2 return v, vn
Sestavite funkcijo odstrani(v, x)
, ki kot argumenta prejme referenco na
vozel ter element x
. Funkcija naj verigo popravi, tako da odstrani vozle,
ki kot podatek vsebujejo element x
. Funkcija naj vrne referenco na
začetni vozel verige. Na primer:
>>> v = iz_seznama([7, 5, 2, 5, 3, 5])
>>> v = odstrani(v, 5)
>>> v.vrni_seznam()
[7, 2, 3]
def odstrani(v, x): if v is None: return None if v.podatek != x: v.naslednji = odstrani(v.naslednji, x) return v return odstrani(v.naslednji, x)
Sestavite funkcijo sodi_in_lihi(v)
, ki kot argument prejme referenco na
vozel ter vrne dve verigi, ki jih dobi tako, da v eno zloži vozle, ki vebujejo
sode podatke, v drugo pa vozle, ki vsebujejo lihe podatke. Funkcija naj vrne
par in sicer referenci na začetna vozla v obeh verigah. Na primer:
>>> v = iz_seznama([7, 5, 2, 1, 3, 4, 9, 8])
>>> v1, v2 = sodi_in_lihi(v)
>>> v1.vrni_seznam()
[2, 4, 8]
>>> v2.vrni_seznam()
[7, 5, 1, 3, 9]
def sodi_in_lihi(v): if v is None: return None, None v1, v2 = sodi_in_lihi(v.naslednji) if v.podatek % 2 == 0: v.naslednji = v1 return v, v2 v.naslednji = v2 return v1, v
Razredu Vozel
dodajte metodo je_urejen(self)
, ki vrne True
, če je
verižni seznam urejen naraščajoče in False
, če ni. Zgled:
>>> v = iz_seznama([1, 2, 4, 7, 8])
>>> v.je_urejen()
True
>>> v = iz_seznama([1, 2, 4, 3, 7])
>>> v.je_urejen()
False
class Vozel(Vozel): def je_urejen(self): if self.naslednji is None: return True if self.podatek > self.naslednji.podatek: return False return self.naslednji.je_urejen()
Razredu Vozel
dodajte metodo vstavi_v_urejenega(self, x)
, ki podatek x
vstavi na primerno mesto v verižni seznam. Predpostavka je, da je verižni
seznam urejen. Metoda naj vrne začetni vozel tega verižnega seznama. Zgled:
>>> v = iz_seznama([1, 2, 4, 7, 8])
>>> v = v.vstavi_v_urejenega(3)
>>> v.vrni_seznam()
[1, 2, 3, 4, 7, 8]
class Vozel(Vozel): def vstavi_v_urejenega(self, x): if x <= self.podatek: v = Vozel(x, self) return v if self.naslednji is None: self.naslednji = Vozel(x) else: self.naslednji = self.naslednji.vstavi_v_urejenega(x) return self
Sestavite funkcijo preuredi_parnost(v)
, ki kot argument prejme referenco na
vozel ter verižni seznam tako preuredi, da postavi vse vozle, ki vsebujejo lih
podatek na začetek, vozle, ki vsebujejo sod podatek pa na konec. Funkcija naj
vrne par in sicer referenci na začetna vozla v obeh verigah. Na primer:
>>> v = iz_seznama([7, 5, 2, 1, 3, 4, 9, 8])
>>> v = preuredi_parnost(v)
>>> v.vrni_seznam()
[7, 5, 1, 3, 9, 2, 4, 8]
def pripoji_verigo(v1, v2): p = v1 while p.naslednji is not None: p = p.naslednji p.naslednji = v2 return v1 def preuredi_parnost(v): s, l = sodi_in_lihi(v) return pripoji_verigo(l, s)
Pepi je sestavil verižni seznam in ugotovil, da je elemente nizal v seznam
v napačnem vrstnem redu. Zdaj je treba seznam obrniti, tako da obstoječih
vozlov ne brišemo in ne dodajamo novih. Sestavite funkcijo obrni_na_mestu(v)
,
ki dobi verižni seznam in ga obrne na mestu. Funkcijo mora vrniti referenco
na prvi vozel. Zgled:
>>> v = iz_seznama([7, 5, 2, 1])
>>> v = obrni_na_mestu(v)
>>> v.vrni_seznam()
[1, 2, 5, 7]
def obrni_na_mestu(v): prejsnji = None while v is not None: nasl = v.naslednji v.naslednji = prejsnji prejsnji = v v = nasl return prejsnji
Otroci se bodo igrali skrivalnice. Izbrati morajo nekoga, ki bo mižal, zato
so se vsi postavili v krog. Uporabljajo zelo popularno izštevanko, ki ima n
zlogov. Sestavite funkcijo kdo_mizi(imena, n)
, ki kot argument dobi seznam
imen in naravno število n
. Funkcija naj najprej sestavi krožni seznam (tako
kot verižni seznam, samo da zadnji element kaže na prvega). Nato vozle izločamo
iz kroga, tako da zbrišemo
>>> kdo_mizi(['Mojca', 'Janez', 'Micka', 'Peter', 'Matjaž', 'Jožefa'], 5)
'Mojca'
class Vozel: """ Osnovni sestavni del verižnega seznama. """ def __init__(self, podatek=None, naslednji=None): self.podatek = podatek self.naslednji = naslednji def __str__(self): return str(self.podatek) def vrni_seznam(self): """ Vrni seznam s podatki, ki so shranjeni v vozlih. """ sez = [] p = self while p is not None: sez.append(p.podatek) p = p.naslednji return sez def iz_seznama(l): """ Vrni verižni seznam, ki bo imel kot podatke elemente seznama l. """ prvi = Vozel(l[0]) p = prvi for i in range(1, len(l)): p.naslednji = Vozel(l[i]) p = p.naslednji return prvi def kdo_mizi(imena, n): i = 0 while len(imena) > 1: i = (i + n - 1) % len(imena) del imena[i] return imena[0]
Sestavite še funkcijo zgodovina_izstevanja(imena, n)
, ki naj deluje podobno
kot funkcija iz prve podnaloge, le da vrne seznam, ki vsebuje imena v takem
vrstnem redu, kot smo jih izločali pri izštevanki. Zgled:
>>> zgodovina_izstevanja(['Mojca', 'Janez', 'Micka', 'Peter', 'Matjaž', 'Jožefa'], 5)
['Matjaž', 'Peter', 'Jožefa', 'Janez', 'Micka', 'Mojca']
def zgodovina_izstevanja(imena, n): i = 0 ret = [] while len(imena) > 0: i = (i + n - 1) % len(imena) ret.append(imena[i]) del imena[i] return ret
Zdaj pa sestavite še funkcijo odhajanje_iz_kroga(imena, n)
, ki deluje podobno
kot prejšnja funkcija, le da vrne verižni seznam namesto običajnega seznama.
Vozli naj bodo urejeni tako, da je v zadnjem vozlu shranjeno ime otroka, ki je
najprej zapustil krog. Zgled:
>>> v = odhajanje_iz_kroga(['Mojca', 'Janez', 'Micka', 'Peter', 'Matjaž', 'Jožefa'], 5)
>>> v.vrni_seznam()
['Mojca', 'Micka', 'Janez', 'Jožefa', 'Peter', 'Matjaž']
def odhajanje_iz_kroga(imena, n): i = 0 ret = [] while len(imena) > 0: i = (i + n - 1) % len(imena) ret.append(imena[i]) del imena[i] return iz_seznama(ret[::-1])